package com.pearadmin.modules.sys.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.pearadmin.common.tools.SequenceUtil;
import com.pearadmin.common.web.domain.request.PageDomain;
import com.pearadmin.modules.sys.domain.*;
import com.pearadmin.modules.sys.domain.dto.MsgUserInfoDto;
import com.pearadmin.modules.sys.domain.dto.MsgWebSocketDto;
import com.pearadmin.modules.sys.domain.vo.MsgUserInfoVo;
import com.pearadmin.modules.sys.mapper.WorkCastingMapper;
import com.pearadmin.modules.sys.mapper.WorkOrderMapper;
import com.pearadmin.modules.sys.service.*;
import com.pearadmin.modules.ws.WebSocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工单管理Service业务层处理
 *
 * @author Mr.Ling
 * @date 2021-12-18
 */
@Service
@Slf4j
public class WorkOrderServiceImpl implements IWorkOrderService {
    @Autowired
    private WorkOrderMapper workOrderMapper;
    @Autowired
    private WorkCastingMapper workCastingMapper;
    @Autowired
    private IWorkOrderHistoryService workOrderHistoryService;
    @Autowired
    private ISysNoticeService noticeService;
    @Autowired
    private IInvAnodeService anodeService;
    @Autowired
    private IWorkCarService workCarService;
    @Autowired
    private IWorkOperateService workOperateService;
    @Autowired
    private InvAnodeInputInfoServiceImpl invAnodeInputInfoService;

    /**
     * 查询工单管理
     *
     * @param id 工单管理ID
     * @return 工单管理
     */
    @Override
    public WorkOrder selectWorkOrderById(String id) {
        return workOrderMapper.selectWorkOrderById(id);
    }

    /**
     * 查询工单管理列表
     *
     * @param workOrder 工单管理
     * @return 工单管理
     */
    @Override
    public List<WorkOrder> selectWorkOrderList(WorkOrder workOrder) {
        return workOrderMapper.selectWorkOrderList(workOrder);
    }

    /**
     * 查询工单管理
     *
     * @param workOrder  工单管理
     * @param pageDomain
     * @return 工单管理 分页集合
     */
    @Override
    public PageInfo<WorkOrder> selectWorkOrderPage(WorkOrder workOrder, PageDomain pageDomain) {
        PageHelper.startPage(pageDomain.getPage(), pageDomain.getLimit());
        List<WorkOrder> data = workOrderMapper.selectWorkOrderList(workOrder);
        return new PageInfo<>(data);
    }

    @Override
    public PageInfo<WorkOrder> getOrderList(WorkOrder workOrder, PageDomain pageDomain) {
        PageHelper.startPage(pageDomain.getPage(), pageDomain.getLimit());
        List<WorkOrder> data = workOrderMapper.getOrderList(workOrder);
        return new PageInfo<>(data);
    }

    /**
     * 新增工单管理
     *
     * @param workOrder 工单管理
     * @return 结果
     */
    @Override
    @Transactional
    public int insertWorkOrder(WorkOrder workOrder) {
        //工单当前状态为核验中,工单开启
        workOrder.setStatus("check");
        workOrder.setEnable("1");
        int result = workOrderMapper.insertWorkOrder(workOrder);
        //保存工单历史记录
        workOrderHistoryService.insertWorkOrderHistory(workOrder);
        //记录车队工作记录 车队队长创建
        WorkCar workCar = new WorkCar();
        workCar.setId(SequenceUtil.makeStringId());
        workCar.setOrderId(workOrder.getId());
        workCar.setCreateTime(LocalDateTime.now());
        workCar.setCreateBy(workOrder.getCreateBy());
        workCar.setCreateName(workOrder.getCreateName());
        workCar.setType("new");//新增工单信息
        //记录当前下单的信息
        workCar = buildCarInfo(workOrder, workCar);
        workCarService.insertWorkCar(workCar);
        //给配送人员、收货人、出库人、抄送人推送数据
        msgPush(workOrder);
        return result;
    }

    //工单信息填写
    private WorkCar buildCarInfo(WorkOrder workOrder, WorkCar workCar) {
        Map map = new HashMap<>();
        map.put("acceptId", workOrder.getAccepter());
        map.put("acceptName", workOrder.getAccepterName());
        map.put("sendId", workOrder.getSender());
        map.put("sendName", workOrder.getSenderName());
        map.put("castingDeptId", workOrder.getInvOutDept());
        map.put("castingDeptName", workOrder.getInvOutDeptName());
        map.put("operateDeptId", workOrder.getAcceptDept());
        map.put("operateDeptName", workOrder.getAcceptDeptName());
        map.put("ccList", workOrder.getCarbonCopyList());
        map.put("orderId", workOrder.getId());
        map.put("hignNum", workOrder.getHighNum());
        map.put("lowNum", workOrder.getLowNum());
        map.put("otherNum", workOrder.getOtherNum());
        workCar.setContent(JSONUtil.toJsonStr(JSONUtil.parseObj(map)));
        return workCar;
    }

    /**
     * 修改工单管理
     *
     * @param workOrder 工单管理
     * @return 结果
     */
    @Override
    @Transactional
    public int updateWorkOrder(WorkOrder workOrder) {
        //车队完成拍照，点击完成核验，记录浇筑信息，记录出库信息 记录车队工作记录
        if ("send".equals(workOrder.getStatus())) {
            Map<String, Object> params = workOrder.getParams();
            List<Map<String, String>> invAnodes = (List) params.get("invAnodes");
            List<InvAnode> list = new ArrayList<>();
            for (Map<String, String> map : invAnodes) {
                InvAnode invAnode = new InvAnode();
                String anodeCode = map.get("anodeCode");
                String blockType = map.get("blockType");
                if (!StringUtils.isEmpty(anodeCode)) {
                    invAnode.setAnodeCode(anodeCode);
                }
                if (!StringUtils.isEmpty(blockType)) {
                    invAnode.setBlockType(blockType);
                }
                if (!StringUtils.isEmpty(anodeCode)&&!StringUtils.isEmpty(blockType)) {
                    list.add(invAnode);
                }
            }
            //记录出库信息
            WorkCasting casting = new WorkCasting();
            casting.setId(SequenceUtil.makeStringId());
            casting.setOrderId(workOrder.getId());
            casting.setOperateType("out");
            casting.setCreateBy(workOrder.getInvOutBy());
            casting.setCreateName(workOrder.getInvOutName());
            casting.setCreateTime(LocalDateTime.now());
            casting.setNum((long) list.size());
            casting.setDeptId(workOrder.getInvOutDept());
            casting.setDeptName(workOrder.getInvOutDeptName());
            //记录出库详细记录,此时invAnode 含有的数据是 导杆编号和类型
            for (InvAnode invAnode : list) {
                invAnode.setId(SequenceUtil.makeStringId());
                invAnode.setCastingId(casting.getId());
                invAnode.setDeptId(casting.getDeptId());
                invAnode.setDeptName(casting.getDeptName());
                invAnode.setAcceptName(workOrder.getAccepterName());
                invAnode.setDirectionId(workOrder.getAcceptDept());//出库去向最终部门id
                invAnode.setDirectionName(workOrder.getAcceptDeptName());//出库去向部门信息
                invAnode.setCreateTime(LocalDateTime.now());
                invAnode.setCreateName(casting.getCreateName());
                invAnode.setNum(-1);
                anodeService.insertInvAnode(invAnode);
                //修改导杆的使用情况，将当前的投入导杆设置为已使用
                InvAnodeInputInfo invAnodeInputInfo = invAnodeInputInfoService.selectByAnodeCode(invAnode.getAnodeCode());
                invAnodeInputInfo.setStatus("1");//将该导杆信息改为
                invAnodeInputInfoService.updateInvAnodeInputInfo(invAnodeInputInfo);
            }
            workCastingMapper.insertWorkCasting(casting);
            //记录车队工作信息 车队配送人员记录
            WorkCar workCar = new WorkCar();
            workCar.setId(SequenceUtil.makeStringId());
            workCar.setOrderId(workOrder.getId());
            workCar.setCreateName(workOrder.getSenderName());
            workCar.setCreateTime(LocalDateTime.now());
            workCar.setCreateBy(workOrder.getSender());
            workCar.setType("check");//核对验收
            Map map = new HashMap<>();
            map.put("base", buildCarInfo(workOrder, workCar).getContent());
            map.put("out", workOrder.getContent());
            workCar.setContent(JSONUtil.toJsonStr(JSONUtil.parse(map)));//记录图片信息
            workCar.setAnodeData(JSONUtil.toJsonStr(workOrder.getParams()));//记录车队验收的导杆信息
            workCarService.insertWorkCar(workCar);
            //更新工单的出库时间
            workOrder.setInvOutTime(LocalDateTime.now());
            workOrder.setUpdateName(workOrder.getSenderName());
            workOrder.setUpdateBy(workOrder.getSender());
            workOrder.setUpdateTime(LocalDateTime.now());
        } else if ("over".equals(workOrder.getStatus())) { //订单完成后需要做的事情
            //记录车队添加记录  车队配送人员记录
            WorkCar workCar = new WorkCar();
            workCar.setId(SequenceUtil.makeStringId());
            workCar.setOrderId(workOrder.getId());
            workCar.setCreateName(workOrder.getSenderName());
            workCar.setCreateTime(LocalDateTime.now());
            workCar.setCreateBy(workOrder.getSender());
            workCar.setType("over");//配送完成
            Map map = new HashMap<>();
            map.put("base", buildCarInfo(workOrder, workCar).getContent());
            map.put("out", workOrder.getContent());
            workCar.setContent(JSONUtil.toJsonStr(JSONUtil.parse(map)));//记录图片信息+基础信息
            WorkCar car = new WorkCar();
            car.setOrderId(workOrder.getId());
            car.setType("check");
            List<WorkCar> workCars = workCarService.selectWorkCarList(car);
            if (CollectionUtil.isNotEmpty(workCars)) {
                WorkCar wc = workCars.get(0);
                workCar.setAnodeData(wc.getAnodeData());
            }
            //从配送历史里面获取anodeData数据
            String anodeData = workCarService.selectAnodeCodeByOrderId(workOrder.getId());
            if (anodeData != null) {
                workCar.setAnodeData(anodeData);
            }
            workCarService.insertWorkCar(workCar);
            workOrder.setContent(workCar.getContent());
            //记录运行验收流程
            WorkOperate workOperate = new WorkOperate();
            workOperate.setId(SequenceUtil.makeStringId());
            workOperate.setOperateType("check");//验收流程
            workOperate.setOrderId(workOrder.getId());
            workOperate.setContent(workOrder.getContent());//记录图片信息
            workOperate.setCreateBy(workOrder.getAccepter());
            workOperate.setCreateName(workOrder.getAccepterName());
            workOperate.setCreateTime(LocalDateTime.now());
            workOperateService.insertWorkOperate(workOperate);
            workOrder.setAcceptTime(LocalDateTime.now());
            workOrder.setUpdateName(workOrder.getAccepterName());
            workOrder.setUpdateBy(workOrder.getAccepter());
            workOrder.setUpdateTime(LocalDateTime.now());
        } else if ("delete".equals(workOrder.getStatus())) {//如果当前的状态是删除订单的话
            //车队记录删除订单记录
            WorkCar workCar = new WorkCar();
            workCar.setId(SequenceUtil.makeStringId());
            workCar.setOrderId(workOrder.getId());
            workCar.setCreateName(workOrder.getCreateName());
            workCar.setCreateTime(LocalDateTime.now());
            workCar.setCreateBy(workOrder.getCreateBy());
            workCar.setType("delete");//配送完成
            workCar.setContent(buildCarInfo(workOrder, workCar).getContent());//图片信息+基础信息
            workCarService.insertWorkCar(workCar);
            workOrder.setUpdateName(workOrder.getCreateName());
            workOrder.setUpdateBy(workOrder.getCreateBy());
            workOrder.setUpdateTime(LocalDateTime.now());

        }
        int result = workOrderMapper.updateWorkOrder(workOrder);
        //工单历史记录保存
        workOrderHistoryService.insertWorkOrderHistory(workOrder);
        //消息推送
        msgPush(workOrder);
        return result;
    }

    /**
     * 消息推送
     *
     * @param workOrder
     */
    private void msgPush(WorkOrder workOrder) {
        List<MsgUserInfoDto> msgUserInfo = new ArrayList<>();
        msgUserInfo.add(new MsgUserInfoDto(workOrder.getCreateBy(), workOrder.getCreateName()));//发起人
        msgUserInfo.add(new MsgUserInfoDto(workOrder.getSender(), workOrder.getSenderName()));//配送人
        msgUserInfo.add(new MsgUserInfoDto(workOrder.getAccepter(), workOrder.getAccepterName()));//收货人
        msgUserInfo.add(new MsgUserInfoDto(workOrder.getInvOutBy(), workOrder.getInvOutName()));//出库人
        //处理抄送人信息
        List<MsgUserInfoVo> vos = JSONArray.parseArray(workOrder.getCarbonCopyList(), MsgUserInfoVo.class);
        for (MsgUserInfoVo vo : vos) {
            msgUserInfo.add(new MsgUserInfoDto(vo.getUserId(), vo.getUserName()));
        }
        //统一发送消息
        for (MsgUserInfoDto dto : msgUserInfo) {
            //组装消息
            SysNotice notice = new SysNotice();
            notice.setId(SequenceUtil.makeStringId());
            notice.setAccept(dto.getUserId());
            notice.setAcceptName(dto.getUserName());
            //如果当前的工单状态处于未核验(check)的话，当前消息就是车队队长发送的
            if ("check".equals(workOrder.getStatus())) {
                notice.setTitle("车队发起工单");
                notice.setType("check");
                notice.setContent("当前工单： " + workOrder.getId() + " 处于待核验的状态");
                notice.setSender(workOrder.getCreateBy());
                notice.setCreateBy(workOrder.getCreateBy());
                notice.setSenderName(workOrder.getCreateName());//消息发送人为车队队长
                log.info("当前工单状态：{}，车队队长核验数据并发送消息，当前消息推送人：{}", workOrder.getStatus(), notice.getSenderName());
            } else if ("send".equals(workOrder.getStatus())) { //如果工单当前状态处于配送中(send)配送中话，当前消息就是车队班组员工发送的
                notice.setTitle("配送班组配送中");
                notice.setType("check");
                notice.setContent("当前工单： " + workOrder.getId() + " 处于配送中的状态");
                notice.setSender(workOrder.getSender());
                notice.setCreateBy(workOrder.getSender());
                notice.setSenderName(workOrder.getSenderName());//消息发送人是车队员工
                log.info("当前工单状态：{}，车队班组核验数据并发送消息，当前消息推送人：{}", workOrder.getStatus(), notice.getSenderName());
            } else if ("delete".equals(workOrder.getStatus())) {//消息发送人为车队队长
                notice.setTitle("车队删除工单");
                notice.setType("delete");
                notice.setContent("当前工单： " + workOrder.getId() + " 处于失效状态");
                notice.setSender(workOrder.getCreateBy());
                notice.setCreateBy(workOrder.getCreateBy());
                notice.setSenderName(workOrder.getCreateName());//消息发送人是运行班组的接收人
                log.info("当前工单状态：{}，车队删除工单，当前消息推送人：{}", workOrder.getStatus(), notice.getCreateName());
            } else { //如果工单当前状态处于完成(over)状态的话，当前信息就是运行班组的人发送的
                notice.setTitle("运行接收工单");
                notice.setType("over");
                notice.setContent("当前工单： " + workOrder.getId() + " 处于完成状态");
                notice.setSender(workOrder.getAccepter());
                notice.setCreateBy(workOrder.getAccepter());
                notice.setSenderName(workOrder.getAccepterName());//消息发送人是运行班组的接收人
                log.info("当前工单状态：{}，运行班组确认并发送消息，当前消息推送人：{}", workOrder.getStatus(), notice.getSenderName());
            }
            notice.setCreateTime(LocalDateTime.now());
            notice.setOrderId(workOrder.getId());
            notice.setStatus("0");//表示未读
            //保存消息
            noticeService.insertSysNotice(notice);
            log.info("消息保存成功：{}", JSONUtil.toJsonStr(notice));
            //开始推送消息,消息内容，发送人xx给你发送了一条下消息
            MsgWebSocketDto msg = new MsgWebSocketDto(
                    notice.getId(), notice.getSenderName() + "给你发送了一条消息");
            log.info("发送前的组装消息：{}", JSONUtil.toJsonStr(msg));
            //判断用户是否在线，如果不在线的话就不给推送，在用户登录的时候进行推送未读消息
            WebSocketUtil.send(JSONUtil.toJsonStr(msg), dto.getUserId());
            log.info("发送结束时间：{}", DateUtil.now());
        }
    }

    /**
     * 删除工单管理对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteWorkOrderByIds(String[] ids) {
        return workOrderMapper.deleteWorkOrderByIds(ids);
    }

    /**
     * 删除工单管理信息
     *
     * @param id 工单管理ID
     * @return 结果
     */
    @Override
    public int deleteWorkOrderById(String id) {
        return workOrderMapper.deleteWorkOrderById(id);
    }
}
